package my.lotu.util;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.hamcrest.core.IsEqual;

import my.lotu.bean.Daymeal;
import my.lotu.bean.Food;
import my.lotu.bean.Meal;
import my.lotu.bean.Plan;
import my.lotu.dao.DaymealDAO;
import my.lotu.dao.FoodDAO;
import my.lotu.dao.MealDAO;
import my.lotu.dao.PlanDAO;

public class PlanFactory implements IPlanFactory {
	
	private static List<Food> listFoods=null;
	private static List<Meal> listMeals=null;
	private static List<Daymeal> listDaymeals=null;
	private FoodDAO foodDAO;
	private MealDAO	mealDAO;
	private DaymealDAO daymealDAO;
	private PlanDAO planDAO;

	
	/**
	 * 根据plan查找获取对应的Daymeal集合
	 */
	@Override
	public List<Daymeal> getDaymealList(Plan plan) {
		int[] arrays=getArrayIds(plan.getDayMealId(), " ");
		
		List<Daymeal> list=new ArrayList<Daymeal>();
		for(int i=0;i<arrays.length;i++){
			list.add(daymealDAO.findById(arrays[i]));
		}
		return list;
	}
	
	/**
	 * 根据Daymeal查找获取对应Meal集合
	 */
	@Override
	public List<Meal> getMealList(Daymeal daymeal) {
		List<Meal> list=new ArrayList<Meal>();
		list.add(mealDAO.findById(daymeal.getBreakfast()));
		list.add(mealDAO.findById(daymeal.getLunch()));
		list.add(mealDAO.findById(daymeal.getDinner()));
		return list;
	}
	
	/**
	 * 根据Meal查找获取对应的Food集合
	 */
	@Override
	public List<Food> getFoodByMeal(Meal meal) {
		int[] arrays=getArrayIds(meal.getFoodId(), " ");
		List<Food> list=new ArrayList<Food>();
		for(int i=0;i<arrays.length;i++){
			list.add(getFoodDAO().findById(arrays[i]));
		}
		return list;
	}
	
	/**
	 * 把传入的字符串string根据对应的分隔符split分解获取对应的int数组
	 * @param string
	 * @param split
	 * @return
	 */
	private int[] getArrayIds(String string,String split){
		
		String[] strings=string.split(split);
		int[] arrays=new int[strings.length];
		for(int i=strings.length-1;i>-1;i--){
			arrays[i]=Integer.parseInt(strings[i]);
		}
		return arrays;
	}
	
	/**
	 * 把传入的int数组和分隔符转换为对应的字符串
	 * @param array
	 * @param split
	 * @return
	 */
	private String getStringIds(int[] array,String split){
		String string="";
		for(int i=0;i<array.length;i++){
			string=string+array[i]+split;
		}
		return string.substring(0, string.length()-1);
	}
	
	/**
	 * 根据用户传入的参数生成对应的方案
	 * @param plan
	 * @return
	 */
	public Plan getPlan(Plan plan) {
		/**
		 * 获取方案中对应的Daymeal（每日用餐）集合，并计算相关信息
		 */
		List<Daymeal> daymeals=getDaymeals(plan);
		/**
		 * plan信息设置
		 */
		double calorie=0;
		String daymealsIdString="";
		for(int i=0;i<plan.getDay();i++){
			calorie+=daymeals.get(i).getCalorie();
			daymealsIdString=daymealsIdString+" "+daymeals.get(i).getId();
		}
		plan.setCalorie(calorie);
		plan.setDayMealId(daymealsIdString.substring(1));
		
		/**
		 * 把方案存储到数据库
		 */
		planDAO.save(plan);

		return plan;
	}
	
	/**
	 * 根据所给方案信息，生成对应的每日用餐
	 * @param plan
	 * @return
	 */
	private List<Daymeal> getDaymeals(Plan plan){
		int day=plan.getDay();
		double money=plan.getCost();
		List<Daymeal> list=new ArrayList<Daymeal>();
		for(int i=0;i<day;i++)
		{
			//设置每天平均花多少，如果要做优化的话，可以改成策略模式，规定每天要花多少
			Daymeal daymeal=new Daymeal();
			daymeal.setCost(money/day);
			List<Meal> meals=getMeals(daymeal);
			//根据获取的meals，设置对应daymeal
			double cost=0;
			double calorie=0;
			/**
			 * daymeal信息设置
			 */
			for(int j=0;j<meals.size();j++){
				if(meals.get(j).getType().equals("Breakfast")){
					daymeal.setBreakfast(meals.get(j).getId());				
				}else if(meals.get(j).getType().equals("Lunch")){
					daymeal.setLunch(meals.get(j).getId());					
				}else if(meals.get(j).getType().equals("Dinner")){
					daymeal.setDinner(meals.get(j).getId());
				}
				cost+=meals.get(j).getCost();
				calorie+=meals.get(j).getCalorie();
			}
			daymeal.setCalorie(calorie);
			daymeal.setCost(cost);
			/**
			 * 数据库存入Daymeal
			 */
			daymealDAO.save(daymeal);
			
			list.add(daymeal);
		}
		return list;
	}
	
	/**
	 * 根据所给的每日用餐信息生成对应的早中晚用餐
	 * @param daymeal
	 * @return
	 */
	private List<Meal> getMeals(Daymeal daymeal) {
		List<Meal> list=new ArrayList<Meal>();
		
		double money=daymeal.getCost();
		
		Meal breakfast=new Meal();
		Meal lunch=new Meal();
		Meal dinner=new Meal();
		/**
		 * 早中晚每餐占比，3：5：5
		 */
		breakfast.setCost(money*3/13);
		lunch.setCost(money*5/13);
		dinner.setCost(money*5/13);
		do{
			breakfast=getBreakfast(breakfast);
			lunch=getLunch(lunch);
			dinner=getDinner(dinner);
		}while(!isDaymealReasonable(breakfast,lunch,dinner));
		
		
		/**
		 * 每餐信息存入数据库
		 * 
		 */
		mealDAO.save(dinner);
		mealDAO.save(lunch);
		mealDAO.save(breakfast);
		
		list.add(breakfast);
		list.add(lunch);
		list.add(dinner);
		
		return list;
	}
	private boolean isDaymealReasonable(Meal breakfast, Meal lunch, Meal dinner) {
		if(isEqual(breakfast,lunch) || isEqual(breakfast,dinner) || isEqual(dinner, lunch)){
			return false;
		}
		return true;
	}

	private boolean isEqual(Meal breakfast, Meal lunch) {
		if(breakfast.getCalorie()==lunch.getCalorie() && breakfast.getCost()==lunch.getCost()){
			return true;
		}
		return false;
	}

	/**
	 * 根据指定的食物类型获取对应的食物集合
	 * @param type
	 * @return
	 */
	private List<Food> getFoodListByTypes(String[] types){
		List<Food> list=new ArrayList<Food>();
		for(int i=0;i<types.length;i++){
			String string=types[i];
			if(list.addAll(getFoodsByType2(string))){
				System.out.println(i+"is ok"+string);
			}else{
				System.out.println("addall is faile");
			}
		}
		
		return list;
	}
	/**
	 * 在给定的Food集合中随机获取指定数量的食物集合(不重复)
	 * @param list
	 * @param count
	 * @return
	 */
	private List<Food> getRandomFood(List<Food> list,int count){
		
		List<Food> listget=new ArrayList<Food>();
		Food food=null;
		Random random=new Random();
		random.setSeed(new Date().getTime());
		
		for(int i=0;i<count;i++){	
			int rand=random.nextInt(list.size());
			food=list.get(rand);
			if(!listget.contains(food)){
				listget.add(food);
			}
				
		}
		return listget;
	}
	
	private boolean isMealReasonable(double cost, double calorie, Meal dinner) {
		/**
		 * 限定条件：
		 * 1.食物的总价格不可高于该餐花费
		 * 2.食物不可重复
		 * 3.因数据库存在不规范数据，所以设置最低总花费4元。
		 */
		
		if(cost==0 && calorie==0){
			return false;
		}
		if(cost>dinner.getCost() ||cost<4 || calorie<300 || calorie>1000){
			return false;
		}
		return true;
	}

	private Meal getDinner(Meal dinner) {

		double cost=0;
		double calorie=0;
		String idsString="";
		
		String[] typesStrings={"面食","菜肴"};
		
		List<Food> foods=getFoodListByTypes(typesStrings);
		List<Food> randFoods=null;
		/**
		 * 计算随机获取的食物总信息
		 */
		while(!isMealReasonable(cost,calorie,dinner)){
			int count=3;
			randFoods=getRandomFood(foods, count);
			cost=0;
			calorie=0;
			
			int[] array=new int[randFoods.size()];
			for(int i=0;i<randFoods.size();i++){
				Food food=randFoods.get(i);
				array[i]=food.getId();
				cost+=food.getPrice();
				calorie+=food.getCalorie();
			}
			idsString=getStringIds(array, " ");
		}
		/**
		 * 设置这次用餐的信息
		 */

		dinner.setCalorie(calorie);
		dinner.setCost(cost);
		dinner.setType("Dinner");
		dinner.setFoodId(idsString);
		return dinner;
	}

	
	private Meal getLunch(Meal lunch) {
		double cost=0;
		double calorie=0;
		String idsString="";
		
		String[] typesStrings={"面食","菜肴"};
		
		List<Food> foods=getFoodListByTypes(typesStrings);
		List<Food> randFoods=null;
		/**
		 * 计算随机获取的食物总信息
		 */
		while(!isMealReasonable(cost,calorie,lunch)){
			randFoods=getRandomFood(foods, 3);
			cost=0;
			calorie=0;
			int[] array=new int[randFoods.size()];
			for(int i=0;i<randFoods.size();i++){
				Food food=randFoods.get(i);
				array[i]=food.getId();
				cost+=food.getPrice();
				calorie+=food.getCalorie();
			}
			idsString=getStringIds(array, " ");
			
		}
		/**
		 * 设置这次用餐的信息
		 */
	
		lunch.setCalorie(calorie);
		lunch.setCost(cost);
		lunch.setType("Lunch");
		lunch.setFoodId(idsString);
		return lunch;
	}

	private Meal getBreakfast(Meal breakfast) {
		double cost=0;
		double calorie=0;
		String idsString="";
		
		String[] typesStrings={"面食","菜肴"};
		
		List<Food> foods=getFoodListByTypes(typesStrings);
		List<Food> randFoods=null;
		/**
		 * 计算随机获取的食物总信息
		 */
		while(!isMealReasonable(cost,calorie,breakfast)){
			randFoods=getRandomFood(foods, 3);
			cost=0;
			calorie=0;
			int[] array=new int[randFoods.size()];
			for(int i=0;i<randFoods.size();i++){
				Food food=randFoods.get(i);
				array[i]=food.getId();
				cost+=food.getPrice();
				calorie+=food.getCalorie();
			}
			idsString=getStringIds(array, " ");
			
		}
		/**
		 * 设置这次用餐的信息
		 */
		
		breakfast.setCalorie(calorie);
		breakfast.setCost(cost);
		breakfast.setType("Breakfast");
		breakfast.setFoodId(idsString);
		return breakfast;
	}

	private List<Food> getFoodsByType2(String string) {
		List<Food> list=new ArrayList<Food>();
		for(int i=getListFoods().size()-1;i>=0;i--){
			if(getListFoods().get(i).getType2().equals(string)){
				list.add(getListFoods().get(i));
			}
		}
		return list;
	}
	/**
	 * setter和getter方法
	 * @return
	 */
	
	public FoodDAO getFoodDAO() {
		return foodDAO;
	}
	public void setFoodDAO(FoodDAO foodDAO) {
		this.foodDAO = foodDAO;
	}
	public MealDAO getMealDAO() {
		return mealDAO;
	}
	public void setMealDAO(MealDAO mealDAO) {
		this.mealDAO = mealDAO;
	}
	public DaymealDAO getDaymealDAO() {
		return daymealDAO;
	}
	public void setDaymealDAO(DaymealDAO daymealDAO) {
		this.daymealDAO = daymealDAO;
	}
	public PlanDAO getPlanDAO() {
		return planDAO;
	}
	public void setPlanDAO(PlanDAO planDAO) {
		this.planDAO = planDAO;
	}

	@SuppressWarnings("unchecked")
	public List<Meal> getListMeals() {
		if(listMeals==null){
			listMeals=(List<Meal>)mealDAO.findAll();
		}
		return listMeals;
	}

	public void setListMeals(List<Meal> listMeals) {
		PlanFactory.listMeals = listMeals;
	}

	@SuppressWarnings("unchecked")
	public List<Daymeal> getListDaymeals() {
		if(listDaymeals==null){
			listDaymeals=(List<Daymeal>)daymealDAO.findAll();
		}
		return listDaymeals;
	}

	public void setListDaymeals(List<Daymeal> listDaymeals) {
		PlanFactory.listDaymeals = listDaymeals;
	}
	@SuppressWarnings("unchecked")
	public List<Food> getListFoods() {
		if(listFoods==null){
			listFoods=(List<Food>)foodDAO.findAll();
			listFoods=listFoods.subList(0, listFoods.size());
		}
		return listFoods;
	}
	public void setListFoods(List<Food> listFoods) {
		PlanFactory.listFoods = listFoods;
	}
	
}
